﻿#include "codegeneratortest.h"
#include "common/logger/logger.h"
#include <common/codeimagegenerate/codeimageconfig.h>
#include <common/codeimagegenerate/codeimagegenerator.h>

CodeGeneratorTest::CodeGeneratorTest(QObject* parent):QObject(parent)
{

}

CodeGeneratorTest::~CodeGeneratorTest()
{
}


void CodeGeneratorTest::initTestCase()
{

	// 创建 50x50 像素的青色图标（用于二维码）
	QImage icon(50, 50, QImage::Format_ARGB32);
	icon.fill(QColor(0, 255, 255));
	icon.save("icon.png");

	//创建存储目录
    m_rootDir = "./testCode/";
	QStringList dir={"default/","size/","icon/defaultSize","icon/customSize","custom/","invalid/"};
	for (const auto& d:dir)
	{
		m_rootDir+=d;
		if (!createTestDir(m_rootDir))
		{
			QFAIL("Failed to create root test directory!");
			return;
		}
		m_rootDir.chop(d.length());
	}
}

// 测试1：默认效果（静态方法）
void CodeGeneratorTest::testDefaultStaticMethods()
{
	LOG_INFO("============================================================================");
	LOG_INFO("测试1，此时默认效果");
    // 1. 测试静态方法生成默认二维码（默认QR_CODE）
	QString barcodeSavePath = m_rootDir + "default/qrcode_Default.png";
	QImage qrImage = CodeImageGenerator::createQRCode("TestQR_Default");
	QVERIFY2(verifyImageValid(qrImage, barcodeSavePath), "Default QR static generate failed!");

    // 2. 测试静态方法生成默认条形码（默认CODE_128）
	barcodeSavePath = m_rootDir + "default/Barcode_Default.png";
    QImage barcodeImage = CodeImageGenerator::createBarcode("TestBarcode_Default");
    QVERIFY2(verifyImageValid(barcodeImage, barcodeSavePath), "Default Barcode static generate failed!");

	//3. 只修改生成类型，测试DataMatrix
	barcodeSavePath= m_rootDir + "default/MicroQR_Default.png";
	CodeImageConfig qrConfig;
	qrConfig.setType(BarcodeType::MICRO_QR);
	CodeImageGenerator generator;
	// 数据不能过大
	barcodeImage = generator.generate("TDefault", qrConfig);
	QVERIFY2(verifyImageValid(barcodeImage, barcodeSavePath), "Default DataMatrix static generate failed!");

	// 4. 只修改生成类型,测试EAN_13,最后一位为校验位
	barcodeSavePath = m_rootDir + "default/EAN13_Default.png";
	qrConfig.setType(BarcodeType::EAN_13);
	barcodeImage = generator.generate("1234567890128", qrConfig);
	QVERIFY2(verifyImageValid(barcodeImage, barcodeSavePath), "Default EAN_13 static generate failed!");
	LOG_INFO("测试1，此时默认效果结束");
	LOG_INFO("============================================================================");
}

// 测试2：指定尺寸（对象成员函数）
void CodeGeneratorTest::testSpecifiedSizeMemberFunc()
{
	LOG_INFO("============================================================================");
	LOG_INFO("测试2，此时指定尺寸,复用config配置");
	QString path = m_rootDir + "size/";
	QString data= "1234567890128";
	for (auto format:CodeImageGenerator::getSupportedFormats())
	{

		QString qrSavePath=path+barcodeTypeToString(format)+".png";

		CodeImageConfig config;
		config.setType(format)
			  .setSize(QSize(300, 300)); // 统一测试300*300
		CodeImageGenerator generator(config);
		QImage image = generator.generate(data);

		QVERIFY2(verifyImageValid(image, qrSavePath), "QR specified size generate failed!");
	}
	LOG_INFO("测试2，此时指定尺寸结束");
	LOG_INFO("============================================================================");

}

// 测试3：二维码带图标+容错级别
void CodeGeneratorTest::testQRWithIconAndErrorLevel()
{
	LOG_INFO("============================================================================");
	LOG_INFO("测试3，此时二维码带图标");
	QImage iconImage("icon.png");

	IconConfig iconConfig;
	iconConfig.setImage(iconImage)
			  .setScalePercent(20) // 图标占二维码20%大小
			  .setBorderWidth(2)   // 图标边框2px
			  .setDrawRect(true);  // 绘制矩形边框

	int percent[]={5,15,20,25,30,35,45};
	CodeImageGenerator generator;
	for (int i=0;i<7;++i)
	{
		iconConfig.setScalePercent(percent[i]);
		CodeImageConfig qrConfig = CodeImageConfig::defaultQRCode()
				   .setIcon(iconConfig);

		QString qrSavePath = m_rootDir + QString("icon/defaultSize/QR_Icon_Error_%1.png").arg(percent[i]);
		QImage qrImage = generator.generate(QString("TestQR_Icon_HighError_%1").arg(percent[i]), qrConfig);
		QVERIFY2(verifyImageValid(qrImage, qrSavePath), "QR with icon (HIGH error) generate failed!");
	}
	for (int i=0;i<7;++i)
	{
		iconConfig.setScalePercent(percent[i]);
		CodeImageConfig qrConfig = CodeImageConfig::defaultQRCode()
				   .setIcon(iconConfig)
		           .setSize(QSize(222,222));

		QString qrSavePath = m_rootDir + QString("icon/customSize/QR_Icon_Error_%1.png").arg(percent[i]);
		QImage qrImage = generator.generate(QString("TestQR_Icon_HighError_%1").arg(percent[i]), qrConfig);
		QVERIFY2(verifyImageValid(qrImage, qrSavePath), "QR with icon (HIGH error) generate failed!");

	}
	LOG_INFO("测试3，此时二维码带图标结束");
	LOG_INFO("============================================================================");
}

// 测试4：全自定义配置+配置复用
void CodeGeneratorTest::testFullCustomConfigAndReuse()
{
	LOG_INFO("============================================================================");
	LOG_INFO("测试4，此时全自定义配置+配置复用");
	QString path = m_rootDir + "custom/";
	QString data= "1234567890128";

	//此处可以让豆包生成图片，放在bin目录下;自己截屏，不是正方形，不直观
	QImage iconImage("idea.png");
	IconConfig iconConfig;
	iconConfig.setImage(iconImage)
			  .setScalePercent(20) // 图标占二维码20%大小
			  .setBorderWidth(2)   // 图标边框2px
			  .setDrawRect(true);  // 绘制矩形边框
	// 1. 全自定义配置：无安静区+自定义颜色+条形码不显示文本
	CodeImageConfig customConfig;
	customConfig.setSize(QSize(300,300))              // 尺寸
				.setQuietZone(true)                  // 开启安静区
				.setShowText(true)                   // 显示文本
				.setColors(QColor(0, 100, 200),       // 前景色：蓝色
						  QColor(255, 255, 240))     // 背景色：米白色
				.setIcon(iconConfig);				 // 图标配置（仅二维码有效）

	CodeImageGenerator generator;

	for (auto format:CodeImageGenerator::getSupportedFormats())
	{
		customConfig.setType(format);
		if (format == BarcodeType::EAN_13)
		{
			customConfig.setShowText(false);
			customConfig.setSize(QSize(200,200));
			customConfig.setColors(QColor(0, 0, 0), QColor(255, 255, 255));
		}
		QImage image = generator.generate(data, customConfig);
		QString savePath = path + barcodeTypeToString(format) + ".png";
		QVERIFY2(verifyImageValid(image, savePath), "Custom config generate failed!");
	}
	LOG_INFO("测试4，此时全自定义配置+配置复用结束");
	LOG_INFO("============================================================================");
}

// 测试5：无效数据校验
void CodeGeneratorTest::testInvalidData()
{
	LOG_INFO("============================================================================");
	LOG_INFO("测试5，此时无效数据校验");
	// 1. 测试EAN_13无效数据（非数字+长度12位）
	CodeImageConfig eanConfig = CodeImageConfig::defaultBarcode();
	CodeImageGenerator generator;
	eanConfig.setType(BarcodeType::EAN_13);
	QImage eanInvalid1 = generator.generate("123456789012", eanConfig); // 12位非数字（假设数据含字母）
	QImage eanInvalid2 = generator.generate("123456789012a", eanConfig);// 13位含字母
	QVERIFY2(eanInvalid1.isNull(), "EAN_13 invalid data (12 digits) should return null!");
	QVERIFY2(eanInvalid2.isNull(), "EAN_13 invalid data (with letter) should return null!");

	// 2. 测试QR_CODE无效数据（空数据）
	CodeImageConfig qrConfig = CodeImageConfig::defaultQRCode();
	QImage qrInvalid = generator.generate("", qrConfig);// 空数据
	QVERIFY2(qrInvalid.isNull(), "QR_CODE empty data should return null!");

	// 3. 测试CODE_128无效数据（超长48字符）
	CodeImageConfig code128Config = CodeImageConfig::defaultBarcode();
	code128Config.setType(BarcodeType::CODE_128);
	QString longData(50, 'a');// 50个字符（超过48）
	QImage code128Invalid = generator.generate(longData, code128Config);
	QVERIFY2(code128Invalid.isNull(), "CODE_128 long data (50 chars) should return null!");
	LOG_INFO("测试5，此时无效数据校验结束");
	LOG_INFO("============================================================================");

}
void CodeGeneratorTest::cleanUpTestcase()
{
	qInfo() << "Test completed! All images saved to:" << QDir(m_rootDir).absolutePath();
}

// 辅助函数：创建目录
bool CodeGeneratorTest::createTestDir(const QString& dirPath)
{
	QDir dir(dirPath);
	if (!dir.exists()) {
		return dir.mkpath("."); // 递归创建目录
	}
	return true;
}

// 辅助函数：验证图片有效性（非空+保存成功）
bool CodeGeneratorTest::verifyImageValid(const QImage& image, const QString& savePath)
{
	// 1. 验证图片非空
	if (image.isNull())
	{
		qWarning() << "Image is null:" << savePath;
		return false;
	}
	// 3. 保存图片并验证保存成功
	if (!image.save(savePath))
	{
		qWarning() << "Failed to save image:" << savePath;
		return false;
	}
	qInfo() << "Image saved successfully:" << savePath;
	return true;
}

QString CodeGeneratorTest::barcodeTypeToString(BarcodeType type) {
	static const QMap<BarcodeType, QString> typeMap = {
		{BarcodeType::QR_CODE, "QR_CODE"},
		{BarcodeType::CODE_128, "CODE_128"},
		{BarcodeType::EAN_13, "EAN_13"},
		{BarcodeType::MICRO_QR, "MICRO_QR"}
	};
	auto it = typeMap.find(type);
	return (it != typeMap.end()) ? *it : "UNKNOWN_BARCODE_TYPE";
}

int main(int argc, char** argv)
{
	CodeGeneratorTest tc;
	return QTest::qExec(&tc, argc, argv);// qExec 会把失败信息打印到 stdout
}
